Step FunctionsにLambdaからデータを渡してみた
こんにちは、臼田です。
みなさんLambdaしてますか?
今日は、ちょっとしたwebページの更新チェックをしたくてLambdaを使おうと思ったのですが、せっかくなのでStep Functionsで分岐処理をしてみたいなーと思ったのでやってみました。
ちなみに、Step Functions初心者なので、これから始める人と同じ目線で説明していきます。
作りたいもの
最近脆弱性診断ができるAWS Inspectorを触っていたのですが、対応しているCVEのリストがこちらにあり、随時アップデートされています。
このファイルが更新されたことを通知する仕組みが作りたいと思って実装し始めました。
作りたいイメージ
だいたい下記のイメージです。※今後変更される可能性があります
- Step FunctionsからTargetのUpdateを確認するLambdaを実行してレスポンスを取得
- 更新があればTweet用LambdaからTweet
- 途中でエラーが発生したらSESで通知
数回のブログに分けて実装していきます。
今回の範囲
まずはUpdate Checkerをサクッと作って、それをStep Functionsから呼び出してレスポンスを取得してみます。
Webページの更新をチェックするLambda作成
それでは作っていきましょう。
中身のアルゴリズムとしては、該当URLに対してリクエストしてレスポンスヘッダーの「Last-Modified」をチェックして判断する感じにします。
Python 3.6で書いていきます。
コード
import urllib.request from datetime import datetime, timedelta def lambda_handler(event, context): url = "https://s3-us-west-2.amazonaws.com/rules-engine/CVEList.txt" yesterday = datetime.now() - timedelta(1) with urllib.request.urlopen(url) as r: lm_header = r.info()['Last-Modified'] last_modified = datetime.strptime(lm_header, '%a, %d %b %Y %H:%M:%S %Z') print(last_modified) if last_modified > yesterday: result = {"update": True} else: result = {"update": False} return result
URLをハードコーディングしていますが、最初はとりあえずこんな感じでいいでしょう。
Step Functionsでつなぐので、レスポンスはjsonで返すようにします。
動きとしては、デイリーでLast-Modifiedをチェックして、1日以内の更新であれば「update: True」を返します。
本当はタイムゾーンとか気にするべきですが、ターゲットがGMTで返してくれるのと、pytzを利用しないと(色んな意味で)面倒になるので今回は無視します。
外部ライブラリを利用するなら、Serverless Frameworkを使ったほうがいいでしょう。
それでは、Lambdaを作成します。
Lambda作成
マネジメントコンソールからLambda関数を作成します。
コードが既にあるので「Blank Function」を選択します。
現状トリガーは無いのでそのまま「次へ」
名前を適当に入れ「Python 3.6」を選択します。
Update_Checkerは外部へのアクセスのみなので、特にAWSリソースにアクセスする必要はないので適当なロール名でロールを作成して「次へ」進みます。
確認画面で「関数の作成」を押します
作成できたら「テスト」してみます。
入力値は気にしないので「Hello World」のまま実行します。
Updateが無いためfalseが返ってきました。
とりあえず動いたので、画面右上のLambdaのARNを控えます。
Step Functionsの作成
ステートマシンの作成を開始します。
今回は、とりあえずStep FunctionsからLambdaが実行できたらゴールとします。
ので、設計図の「失敗のRetry」をベースに作成します。
ちなみに、設計図を選択すると名前も勝手に変更されてしまうので、ステップ2で設計図を選んでから名前を付けます。
下の方にスクロールしてワークフローを編集します。
今回は「失敗のRetry」をベースにしていますが、この中のStates(1つの実行単位)には「HelloWorld」というStateが定義されています。
Statesには何種類かのTypeがありますが、これは標準的な「Task」というもので、Resourceで指定した要素を実行します。
他にも必要なTypeがありますが、興味があればこちらで確認して下さい。後続のブログでも幾つか解説します。
今回はResourceを先ほど作成したLambdaに変更します。
直接書き換えてもいいですが、どうやらこの画面で編集すると下記のように補完してくれました。
ダブルクリックで入力できました。
Resourceのみ変更したら、「ステートマシンの作成」から作成します。
IAMロールを選択する画面になりますが、Step Functionsがデフォルトで作成したロールが選択されているので、「OK」を選んでこれをそのまま利用します。
作成が完了したので、そのまま実行してみます。
入力値は関係ないのでそのまま「実行の開始」をします。実行IDは自動的に入力されます。
しばらくすると「実行ステータス」が「成功」になります。
グラフ上でも「HelloWorld」が緑色となり成功していることが読み取れます。
出力タブでも作成したLambdaからのレスポンスが確認できました。
とりあえず問題なくStep FunctionsからLambdaを実行できました。
次はエラーを取得したい
Step Functionsをほとんど知らなくても、とりあえずLambdaを実行できました。
次回は、エラーが発生した際の処理をStep Functions上で実装してみたいと思います。
ワークフローでのTask以外のStatesについても調べて解説します。